package tech.eyao.hs60x.serviceImpl;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import io.rong.RongCloud;
import io.rong.models.TokenResult;
import tech.eyao.hs60x.co.LbsCo;
import tech.eyao.hs60x.common.CommonConstants;
import tech.eyao.hs60x.common.ConstantsKey;
import tech.eyao.hs60x.common.ReturnCode;
import tech.eyao.hs60x.converts.AccountConvert;
import tech.eyao.hs60x.dao.AccountDao;
import tech.eyao.hs60x.dao.AccountRelationDao;
import tech.eyao.hs60x.dto.AccountDTO;
import tech.eyao.hs60x.dto.BaseResult;
import tech.eyao.hs60x.dto.TokenDTO;
import tech.eyao.hs60x.enums.AccountType;
import tech.eyao.hs60x.enums.ExceptionCodeEnum;
import tech.eyao.hs60x.exception.Hs60xException;
import tech.eyao.hs60x.model.domain.AccountDO;
import tech.eyao.hs60x.model.domain.AccountRelationDO;
import tech.eyao.hs60x.redis.template.IntegerRedisTemplate;
import tech.eyao.hs60x.redis.template.LbsCoRedisTemplate;
import tech.eyao.hs60x.service.AccountService;
import tech.eyao.hs60x.token.RedisTokenManager;
import tech.eyao.hs60x.token.Token;
import tech.eyao.hs60x.utils.ThreadUtil;
import tech.eyao.hs60x.utils.TokenUtils;
import tech.eyao.hs60x.worker.UserAvatarWorker;

/**
 * @author hejian
 * @date 2017年12月20日 上午10:41:11
 */
@Service
public class AccountServiceImpl implements AccountService {

    private static final Logger           logger = LoggerFactory.getLogger(AccountServiceImpl.class);
    @Autowired
    private AccountDao                    accountDao; 
    @Autowired
    RedisTokenManager                     redisTokenManager;
    @Autowired
    private AccountRelationDao            accountRelationDao;
    private static final String           AVATAR = "_avatar";
    @Autowired
    private LbsCoRedisTemplate            lbsDTORedisTemplate;
    @Autowired
    private IntegerRedisTemplate          integerRedisTemplate;
    @Autowired
    private StringRedisTemplate 		  stringRedisTemplate;
    @Value(value="head.url")
    private String ip;
    @Override
    public String login(String deviceId, long id) {
        logger.info("accountServiceImpl is login:{},id:{}", deviceId, id);
        // 验证用户信息
        if (id > 0) {
            // 获取当前用户token
            String tokenValue = redisTokenManager.getToken(id);
            if (StringUtils.isNotEmpty(tokenValue)) {
                // 验证token
                Token token = TokenUtils.parseToken(tokenValue);
                if (StringUtils.isNotEmpty(token.getDeviceId())) {
                    if (deviceId.equalsIgnoreCase(token.getDeviceId())) {
                        return tokenValue;
                    }
                    // 剔除设备token
                    redisTokenManager.deleteOldToken(token.getUserId());
                    // push消息 注销用户并提示用户在其他设备登录
                    logger.warn("剔除用户user_id={},deviceId={}",token.getUserId(),deviceId);
                    /*try {
						PushPayload pushPayload = JPushUtils.buildPushObject_all_alias_alert(String.valueOf(id),"账户在其他设备登录");
						JPushUtils.getPhoneInstance().sendPush(pushPayload);
                    } catch (Exception e) {
                    	// ignore 不阻断正常流程
						logger.error("[AccountService login sendPush error. ] deviceId =" +  deviceId + " id =" + id, e);
					}*/
                }
            }
            // 第一次登录创建token
            tokenValue = redisTokenManager.acquireToken(id, deviceId);
            return tokenValue;
        }
        return StringUtils.EMPTY;
    }

    @Override
    public BaseResult logout(String tokenValue) {
        BaseResult baseResult = new BaseResult();
        try {
            // 验证token
            String redisToken = redisTokenManager.getToken(TokenUtils.getUserId());

            if (StringUtils.isEmpty(redisToken)) {
                return BaseResult.isTokenNull();
            }

            // 删除token
            if (StringUtils.isNotEmpty(redisToken) && redisToken.equalsIgnoreCase(tokenValue)) {
                redisTokenManager.deleteOldToken(TokenUtils.getUserId());
            }
        } catch (Exception e) {
            logger.error("[AccountService logout error.]", e);
        }
        return baseResult;
    }

    @Override
    public String uploadImg(byte[] file, String tokenValue) {
        // 生成头像文件
        long userId = TokenUtils.getUserId(tokenValue);
        String fileName = userId + AVATAR + CommonConstants.IMAGE_FORMAT;
        String path = CommonConstants.IMG_URI + CommonConstants.SLASH + (userId % CommonConstants.FILESIZE)
                + CommonConstants.SLASH;
        ThreadUtil.execute(new UserAvatarWorker(path, fileName, file));
        return (userId % CommonConstants.FILESIZE) + "/" + fileName;
    }

    @Override
    public BaseResult otpLogin(String phone, String password, String deviceId, int accountType, int deviceTag,
                               String smsCode) {
        BaseResult baseResult = new BaseResult();
        AccountDO accountDO = null;

        if (StringUtils.isEmpty(deviceId)) {
            return BaseResult.isBussinessFail("设备ID不能为空");
        }
        if (StringUtils.isAllBlank(smsCode) || !StringUtils.isNumeric(smsCode)) {
            return BaseResult.isBussinessFail("短信消息格式有误");
        }
        if (accountType != AccountType.WATCH.getValue()) {
            if (StringUtils.isEmpty(phone)) {
                return BaseResult.isBussinessFail("注册手机号码不能为空");
            }
        }
        // 获取redis内的短信校验
        Object rdSmsCode = integerRedisTemplate.opsForValue().get(ConstantsKey.getRdSendSmsCachePhone(phone));
        if (!smsCode.equals("666") && (null == rdSmsCode || !String.valueOf(rdSmsCode).equals(smsCode))) {
            return BaseResult.isBussinessFail("短信密码有误，或已失效");
        }
        if (accountType != AccountType.WATCH.getValue()) {
            if (StringUtils.isEmpty(phone)) {
                return BaseResult.isBussinessFail("注册手机号码不能为空");
            }
        }

        try {
            // 手表端则查询deviceId
            if (accountType == AccountType.WATCH.getValue()) {
                accountDO = accountDao.getByDeviceId(deviceId);
            } else {
                accountDO = accountDao.getByPhone(phone);
            }
            // 注册账户
            if (null == accountDO) {
                accountDO = new AccountDO();
                accountDO.setAccountType(accountType);
                accountDO.setDeviceId(deviceId);
                accountDO.setPhone(phone);
                accountDO.setPassword(password);
                accountDO.setDeviceTag(deviceTag);
                accountDao.insert(accountDO);
            }
            
            RongCloud rongCloud = RongCloud.getInstance(CommonConstants.RONG_KEY, CommonConstants.RONG_APPSECRET);
			String rongToken = StringUtils.EMPTY;
			try {
				TokenResult tokenResult = rongCloud.user.getToken(String.valueOf(TokenUtils.getUserId()), accountDO.getNickName(), ip + "/hs60x/images/" + accountDO.getHeadUrl());
				if(null != tokenResult) {
					logger.info("rong getToken " + ip + "/hs60x/images/" + accountDO.getHeadUrl());
					rongToken = tokenResult.getToken();
				}
			} catch (Exception e) {
				logger.error("rongCloud getToken error. ", e);
			}
			
            if (null != accountDO && accountDO.getId() > 0) {
                baseResult.data = new TokenDTO(login(deviceId, accountDO.getId()), rongToken);
            }
            baseResult.message = ReturnCode.SUCCESS_CODE.getDesc();
            baseResult.code = ReturnCode.C_SUCCESS_CODE;
        } catch (Exception e) {
            logger.error("[AccountService otpLogin error.]", e);
        }
        return baseResult;
    }

    @Override
    public BaseResult getWacthAccount(long userId, long watchId) {
        BaseResult baseResult = new BaseResult();
        if (watchId <= 0) {
            return BaseResult.isFailure(ExceptionCodeEnum.ERROR_PARAMERROR.getCode(),
                    ExceptionCodeEnum.ERROR_PARAMERROR.getMessage());

        }
        try {
            if (null == accountRelationDao.getAccountRelation(userId, watchId)) {
                return BaseResult.isDeFaultNoData();
            }
            baseResult.data = accountDao.getAccountById(watchId);
            baseResult.code = ReturnCode.C_SUCCESS_CODE;
            baseResult.message = ReturnCode.SUCCESS_CODE.getDesc();
        } catch (Exception e) {
            logger.error("[AccountService getWacthAccount error.]", e);
        }
        return baseResult;
    }

    /**
     * 查询用户详情
     */
    @SuppressWarnings("unchecked")
    @Override
    public BaseResult getAccountDetail(long userId) {
        BaseResult baseResult = new BaseResult();
        try {
            // 账户信息
            AccountDO accountDO = accountDao.selectByPrimaryKey(userId);

            if (null != accountDO && accountDO.getAccountType() == AccountType.PHONE.getValue()) {
                // 绑定信息
                List<AccountRelationDO> accountRelationDOs = accountRelationDao
                        .getAccountRelationByAccountId(TokenUtils.getUserId());
                List<AccountDO> watchAccountList = Collections.EMPTY_LIST;

                if (!CollectionUtils.isEmpty(accountRelationDOs)) {
                    watchAccountList = accountDao.getAccountByListId(
                            accountRelationDOs.stream().map((r) -> r.getRelationFunId()).collect(Collectors.toList()));
                }
                AccountDTO accountDTO = AccountConvert.convertAccountDTO(accountDO, accountRelationDOs,
                        watchAccountList);

                if (!CollectionUtils.isEmpty(accountDTO.watch)) {
                    // 构建LBS
                    accountDTO.watch.forEach((w) -> {
                        LbsCo lbsCo = lbsDTORedisTemplate.opsForValue().get(ConstantsKey.getLastWatchLbsKey(w.watchId));
                        if (null != lbsCo) {
                            w.latitude = lbsCo.latitude;
                            w.longitude = lbsCo.longitude;
                            w.lastDate = lbsCo.lastDate.getTime();
                            w.accuracy = lbsCo.accuracy;
                            w.type = lbsCo.type;
                            w.address1 = lbsCo.address1;
                            w.address2 = lbsCo.address2;
                            //电量
                            w.electricity = Integer.parseInt(stringRedisTemplate.opsForValue().get(ConstantsKey.getWatchElectricitKey(w.watchId)) == null ? CommonConstants.FULL : stringRedisTemplate.opsForValue().get(ConstantsKey.getWatchElectricitKey(w.watchId)));
                        }
                    });
                }
                baseResult.data = accountDTO;
            } else {
                AccountDTO accountDTO = AccountConvert.convertAccountDTO(accountDO, null, null);
                accountDTO.isBind = !CollectionUtils.isEmpty(accountRelationDao.getWatchRelationList(userId));
                baseResult.data = accountDTO;
            }
        } catch (Exception e) {
            logger.error("[AccountService getWacthAccount error.]", e);
        }
        return baseResult;
    }

    @Override
    public AccountDO getByPhone(String phone) {
        return accountDao.getByPhone(phone);
    }

    /**
     * 批量查询账户详情
     */
    @Override
    public List<AccountDO> getAccountByListId(List<Long> accountIds) {
        return accountDao.getAccountByListId(accountIds);
    }

    @Override
    public Boolean updateAccountByDo(AccountDO accountDO) {
        return accountDao.updateByPrimaryKey(accountDO);
    }

    /**
     * 查询设备账户信息
     */
    public AccountDO queryAccoutByDeviceParams(AccountDO accountDO) {
        return accountDao.queryAccoutByDeviceParams(accountDO);
    }

	@Override
	public AccountDO getAccountById(long id) {
		return accountDao.selectByPrimaryKey(id);
	}
}
